Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | // Authentication hook
'use client';
import { useState, useEffect, useCallback } from 'react';
import { authService } from '@/services';
import { authCleanup } from '@/utils/authCleanup';
import { User, LoginRequest, UserRole } from '@/types';
import { normalizeRole } from '@/utils/auth';
interface UseAuthReturn {
user: User | null;
isAuthenticated: boolean;
isLoading: boolean;
login: (credentials: LoginRequest) => Promise<{ success: boolean; error?: string }>;
logout: () => Promise<void>;
hasRole: (role: UserRole) => boolean;
hasAnyRole: (roles: UserRole[]) => boolean;
}
export function useAuth(): UseAuthReturn {
const [user, setUser] = useState<User | null>(null);
const [isLoading, setIsLoading] = useState(true);
const isAuthenticated = !!user;
// Initialize auth state
useEffect(() => {
const initAuth = () => {
try {
const storedUser = authService.getStoredUser();
const hasToken = authService.isAuthenticated();
if (storedUser && hasToken) {
// Normalize stored user role and ensure defaults
const roleNormalized = normalizeRole((storedUser as any).role as any);
const userWithDefaults: User = {
...(storedUser as any),
role: roleNormalized,
active: (storedUser as any).active ?? true,
created_at: (storedUser as any).created_at ?? new Date().toISOString()};
setUser(userWithDefaults);
}
} catch (err) {
console.error('Error initializing auth:', err);
// Clear potentially corrupted data
authService.clearStoredUser();
} finally {
setIsLoading(false);
}
};
initAuth();
}, []);
const login = useCallback(async (credentials: LoginRequest) => {
setIsLoading(true);
try {
const result = await authService.login(credentials);
if (result.success) {
const { token, user: userData } = result.data;
// Store auth data
authService.setAuthToken(token);
authService.setStoredUser(userData);
// Convert UserInfo to User format
const userWithDefaults: User = {
...userData,
active: true,
created_at: new Date().toISOString()};
setUser(userWithDefaults);
return { success: true };
} else {
return {
success: false,
error: result.error.details || 'Login failed'
};
}
} catch {
return {
success: false,
error: 'An unexpected error occurred during login'
};
} finally {
setIsLoading(false);
}
}, []);
const logout = useCallback(async () => {
setIsLoading(true);
try {
// Call logout API (will clear token regardless of response)
await authService.logout();
} catch (err) {
console.error('Logout API error:', err);
} finally {
// Always clear local state
authService.clearStoredUser();
authCleanup.clearAllAuthData();
setUser(null);
setIsLoading(false);
}
}, []);
const hasRole = useCallback((role: UserRole): boolean => {
return user?.role === role;
}, [user]);
const hasAnyRole = useCallback((roles: UserRole[]): boolean => {
return user ? roles.includes(user.role) : false;
}, [user]);
return {
user,
isAuthenticated,
isLoading,
login,
logout,
hasRole,
hasAnyRole};
}
|